<template>
  <div id="cyCodeExecuter" :style="dialogStyle">
    <div class="cy-dialog-header">
      <div class="cy-dialog-title">代码执行器</div>
      <button id="cyCodeExecuterClose" class="cy-dialog-close" @click="close">✕✕</button>
    </div>

    <div class="cy-tab-group">
      <button
          v-for="tab in tabs"
          :key="tab.id"
          :class="['cy-tab', { 'cy-tab-active': activeTab === tab.id }]"
          @click="activeTab = tab.id"
      >
        {{ tab.label }}
      </button>
    </div>

    <div class="cy-code-container">
      <textarea
          id="cyCodeInput"
          v-model="code"
          placeholder="输入JavaScript代码..."
          spellcheck="false"
      ></textarea>

      <div class="cy-code-actions">
        <button
            id="executeCode"
            class="cy-btn cy-btn-primary"
            @click="executeCode"
            :disabled="isExecuting"
        >
          <span v-if="!isExecuting">执行代码</span>
          <span v-else>执行中...</span>
        </button>
        <button
            id="clearCode"
            class="cy-btn cy-btn-outline"
            @click="clearCode"
        >
          清空
        </button>
      </div>
    </div>

    <div class="cy-result-container">
      <div class="cy-result-header">
        <span>执行结果</span>
        <button
            id="clearResult"
            class="cy-btn cy-btn-text"
            @click="clearResult"
        >
          清空结果
        </button>
      </div>
      <div id="cyCodeResult" class="cy-result-content">
        <div v-for="(log, index) in executionLogs" :key="index" class="cy-log-entry">
          <div class="cy-log-type" :class="`cy-log-${log.type}`">{{ log.type.toUpperCase() }}</div>
          <div class="cy-log-message">{{ log.message }}</div>
          <div class="cy-log-time">{{ log.time }}</div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, onMounted } from 'vue'

const props = defineProps({
  position: {
    type: Object,
    default: () => ({ x: 0, y: 0 })
  }
})

const emit = defineEmits(['close'])

const tabs = [
  { id: 'page', label: '页面上下文' },
  { id: 'sandbox', label: '沙箱模式' }
]

const activeTab = ref('page')
const code = ref('')
const isExecuting = ref(false)
const executionLogs = ref([])

const dialogStyle = computed(() => ({
  left: `${props.position.x}px`,
  top: `${props.position.y}px`,
  transform: props.position.x === 0 && props.position.y === 0 ? 'translate(-50%, -50%)' : 'none'
}))

// 创建安全的沙箱环境
const createSandbox = () => {
  const iframe = document.createElement('iframe')
  iframe.style.display = 'none'
  document.body.appendChild(iframe)
  return iframe.contentWindow
}

let sandbox = null

onMounted(() => {
  sandbox = createSandbox()
})

// 执行代码
const executeCode = () => {
  if (!code.value.trim()) {
    addLog('error', '请输入要执行的代码')
    return
  }

  isExecuting.value = true
  addLog('info', '开始执行代码...')

  try {
    let result
    const startTime = performance.now()

    if (activeTab.value === 'sandbox') {
      // 沙箱模式执行
      result = sandbox.eval(code.value)
    } else {
      // 页面上下文执行
      result = window.eval(code.value)
    }

    const endTime = performance.now()
    const executionTime = (endTime - startTime).toFixed(2)

    if (result !== undefined) {
      addLog('result', `执行成功 (${executionTime}ms): ${stringifyResult(result)}`)
    } else {
      addLog('info', `代码执行完成 (${executionTime}ms)`)
    }
  } catch (error) {
    addLog('error', `执行错误: ${error.message}`)
    console.error('代码执行错误:', error)
  } finally {
    isExecuting.value = false
  }
}

// 添加日志
const addLog = (type, message) => {
  const now = new Date()
  const timeString = now.toLocaleTimeString()

  executionLogs.value.push({
    type,
    message,
    time: timeString
  })

  // 自动滚动到底部
  setTimeout(() => {
    const resultContainer = document.getElementById('cyCodeResult')
    if (resultContainer) {
      resultContainer.scrollTop = resultContainer.scrollHeight
    }
  }, 10)
}

// 处理不同类型的返回值
const stringifyResult = (result) => {
  if (result === null) return 'null'
  if (result === undefined) return 'undefined'

  try {
    if (typeof result === 'object' || typeof result === 'function') {
      return JSON.stringify(result, null, 2)
    }
    return String(result)
  } catch (e) {
    return result.toString()
  }
}

// 清空代码
const clearCode = () => {
  code.value = ''
}

// 清空结果
const clearResult = () => {
  executionLogs.value = []
}

const close = () => {
  emit('close')
}
</script>

<style scoped>
.cy-code-executer {
  width: 600px;
  max-width: 90vw;
  background: var(--glass-bg);
  border-radius: 12px;
  box-shadow: var(--cyber-shadow);
  backdrop-filter: blur(10px);
  border: var(--neon-border);
  overflow: hidden;
  font-family: var(--cyber-font);
  color: var(--text-primary);
}

.cy-tab-group {
  display: flex;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
  padding: 0 15px;
}

.cy-tab {
  padding: 10px 15px;
  background: transparent;
  border: none;
  color: var(--text-secondary);
  cursor: pointer;
  position: relative;
  font-size: 14px;
  transition: var(--transition);
}

.cy-tab:hover {
  color: var(--text-primary);
}

.cy-tab-active {
  color: #00ff87;
}

.cy-tab-active::after {
  content: '';
  position: absolute;
  bottom: -1px;
  left: 0;
  right: 0;
  height: 2px;
  background: var(--primary-gradient);
}

.cy-code-container {
  padding: 15px;
}

#cyCodeInput {
  width: 100%;
  min-height: 150px;
  background: rgba(0, 0, 0, 0.3);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 6px;
  padding: 10px;
  color: var(--text-primary);
  font-family: 'Consolas', 'Monaco', monospace;
  resize: vertical;
  margin-bottom: 10px;
}

.cy-code-actions {
  display: flex;
  gap: 10px;
}

.cy-result-container {
  padding: 0 15px 15px;
}

.cy-result-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 10px;
  font-size: 14px;
  color: var(--text-secondary);
}

.cy-result-content {
  max-height: 200px;
  overflow-y: auto;
  background: rgba(0, 0, 0, 0.3);
  border-radius: 6px;
  padding: 10px;
  font-family: 'Consolas', 'Monaco', monospace;
  font-size: 13px;
}

.cy-log-entry {
  display: flex;
  margin-bottom: 5px;
  line-height: 1.4;
}

.cy-log-type {
  font-weight: bold;
  margin-right: 8px;
  min-width: 50px;
}

.cy-log-info {
  color: #60efff;
}

.cy-log-error {
  color: #ff1f71;
}

.cy-log-result {
  color: #00ff87;
}

.cy-log-message {
  flex: 1;
  white-space: pre-wrap;
  word-break: break-word;
}

.cy-log-time {
  color: var(--text-secondary);
  font-size: 12px;
  margin-left: 10px;
}
</style>
